package com.qiudao.commonutil.util;


import org.apache.commons.lang3.StringUtils;

import java.security.MessageDigest;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Description: Md5 工具类
 * 依赖 org.apache.commons.lang3
 * @author: gdc
 * @date: 2019/9/1
 * @version 1.0
 */
public class MD5Util {
    private final static char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    public static String encrypt(String source) {
        return encrypt(source.getBytes());
    }

    public static String encrypt(byte[] source) {
        try {
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(source);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char [] str = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = HEX_DIGITS[byte0 >>> 4 & 0xf];
                str[k++] = HEX_DIGITS[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * key按照ASCII字典排序
     * 如果suffix不为空，排序后追加到尾部再做md5签名
     * ex:a=111&b=222&suffix
     *
     * @param map
     * @param suffix
     * @return 返回签名，如果抛出异常，返回null
     */
    public static String encrypt(Map<String, String> map, String suffix) {
        if (map == null || map.isEmpty()) {
            suffix = suffix == null ? StringUtils.EMPTY : suffix;
            return encrypt(suffix);
        }

        List<String> keyList = new LinkedList<>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            keyList.add(entry.getKey());
        }

        Collections.sort(keyList);

        StringBuilder sb = new StringBuilder();
        for (String key : keyList) {
            sb.append(key).append("=").append(map.get(key)).append("&");
        }

        if (suffix != null && suffix.length() > 0) {
            sb.append(suffix);
        } else {
            sb.delete(sb.length() - 1, sb.length());
        }

        System.out.println(sb.toString());
        return encrypt(sb.toString());
    }

}
